
using Microsoft.EntityFrameworkCore;
using Identity.Interface;
using Identity.Models;
using Identity.Contexts;
using System.Threading.Tasks;
using BootstrapBlazor.Components;

namespace Identity.Service;

/// <summary>
/// 
/// </summary>
/// <param name="factory"></param>
class NavigationService(IDbContextFactory<SysContext> factory) : INavigation
{
    private IDbContextFactory<SysContext> DbFactory { get; } = factory;

    /// <summary>
    /// 获得指定用户名可访问的所有菜单集合
    /// </summary>
    /// <param name="userName">当前用户名</param>
    /// <returns>未层次化的菜单集合</returns>
    public  List<Navigation> GetAllMenus(string userName)
    {

        using var context = DbFactory.CreateDbContext();
        var user =   context.Users
            .Include(u => u.UserRoles) // 加载 UserRoles
            .ThenInclude(ur => ur.Role) // 加载 Role
            .FirstOrDefault(u => u.UserName == userName);

        if (user == null)
        {
            // 用户不存在，返回空列表或抛出异常
            return new List<Navigation>();
        }

        // 判断用户是否是管理员
        var isAdmin = user.Roles.Any(r => r.Name == "Administrator");

            // 查询导航数据
             var result= from n in context.Navigationlists
                        join nav in (
                            from u in context.Users
                            join ur in context.UserRoles on u.Id equals ur.UserId
                            join nr in context.Navigationroles on ur.RoleId equals nr.RoleId
                            where  u.UserName == userName // 管理员或当前用户
                            select nr.NavigationId
                        ) on n.Id equals nav
                        orderby n.Application, n.Order
                        select new Navigation
                        {
                            Id = n.Id,
                            ParentId = n.ParentId,
                            Name = n.Name,
                            Order = n.Order,
                            Icon = n.Icon,
                            Url = n.Url,
                            Category = n.Category,
                            Target = n.Target,
                            IsResource = n.IsResource,
                            Application = n.Application,
                            HasChildren = n.HasChildren
                        };

        return isAdmin==true? [.. context.Navigationlists] :[.. result] ; 
        // return context.Set<Navigation>().FromSqlRaw("SELECT n.ID,n.ParentId,n.NAME,n.ORDER,n.Icon,n.Url,n.Category,n.Target,n.IsResource,n.Application,n.HasChildren FROM Navigations n INNER JOIN (SELECT	nr.NavigationID FROM	Users u	INNER JOIN UserRoles ur ON ur.UserID = u.ID	INNER JOIN NavigationRole nr ON nr.RoleID = ur.RoleID WHERE	u.UserName = {0}) nav ON n.ID = nav.NavigationID ORDER BY n.Application,n.ORDER", new[] { userName }).AsNoTracking().ToList();

    }

    public List<Navigation> GetAllMenus()
    {

        using var context = DbFactory.CreateDbContext();
        return context.Set<Navigation>().AsNoTracking().ToList();

    }

    public async Task<bool> SaveAsync(Navigation model, ItemChangedType changedType)
    {
        var context = DbFactory.CreateDbContext();
        if (changedType == ItemChangedType.Add)
        {
            context.Entry(model).State = EntityState.Added;
        }
        else
        {
            context.Entry(model).State = EntityState.Modified;
        }
        return await context.SaveChangesAsync() > 0;
    }
    public async Task<bool> DeleteAsync(IEnumerable<Navigation> models)
    {
        // 通过模型获取主键列数据
        // 支持批量删除
        var context = DbFactory.CreateDbContext();
        context.RemoveRange(models);
        return await context.SaveChangesAsync() > 0;
    }

    public List<string> GetMenusByRoleId(string? roleId)
    {
        using var context = DbFactory.CreateDbContext();

        return context.Navigationroles.Where(s => s.RoleId == roleId).Select(s => s.NavigationId!).AsNoTracking().ToList();
    }



    public bool SaveMenusByRoleId(string? roleId, List<string> menuIds)
    {
        using var dbcontext = DbFactory.CreateDbContext();
        var ret = false;
        try
        {
            dbcontext.Database.ExecuteSqlRaw("delete from NavigationRole where RoleID = {0}", roleId!);
            dbcontext.Set<NavigationRole>().AddRange(menuIds.Select(g => new NavigationRole { NavigationId = g, RoleId = roleId }));
            dbcontext.SaveChanges();
            ret = true;

        }
        catch (Exception)
        {

            throw;
        }

        return ret;
    }
    public bool GetMenusByUsernaem(string? userName, string menu, string appid)
    {
        using var context = factory.CreateDbContext();
        var query =
        // 主查询：从导航表开始
        from n in context.Navigationlists

            // 子查询：获取用户有权限的 NavigationID
        where (
            from u in context.Users
            where u.UserName == userName
            join ur in context.UserRoles on u.Id equals ur.UserId
            join nr in context.Navigationroles on ur.RoleId equals nr.RoleId
            select nr.NavigationId
        ).Contains(n.Id) // 判断导航ID是否在权限范围内

        // 排序规则
        orderby n.Application, n.Order

        // 投影到实体
        select new Navigation
        {
            Id = n.Id,
            ParentId = n.ParentId,
            Name = n.Name,
            Order = n.Order,
            Icon = n.Icon,
            Url = n.Url,
            Category = n.Category,
            Target = n.Target,
            IsResource = n.IsResource,
            Application = n.Application,
            HasChildren = n.HasChildren
        };

        return query.Where(cm => cm.Name == menu && cm.Application == appid).Any();
        // 子查询：获取用户有权限的 NavigationID

    }
}